package logic

import (
	"context"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"gozerogateway/common/errorx"
	"gozerogateway/rpc/model/svcmodel"
	"gozerogateway/rpc/svc/internal/svc"
	"gozerogateway/rpc/svc/svcclient"

	"errors"
	"github.com/zeromicro/go-zero/core/logx"
)

type ServiceAddHttpLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewServiceAddHttpLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ServiceAddHttpLogic {
	return &ServiceAddHttpLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *ServiceAddHttpLogic) ServiceAddHttp(in *svcclient.ServiceAddHttpReq) (*svcclient.ServiceAddHttpResp, error) {
	// todo: add your logic here and delete this line

	if err := l.svcCtx.SvcModel.FindOneByServiceName(l.ctx, in.ServiceName); err == nil {
		return nil, errorx.NewDefaultError("servicename is exist")
	}

	if err := l.svcCtx.SvcHttpModel.FindHttpUrl(l.ctx, &svcclient.ServiceAddHttpReq{
		RuleType: in.RuleType,
		Rule:     in.Rule,
	}); err == nil {
		return nil, errorx.NewDefaultError("rule_type and rule is exist")
	}

	//open trans after provide data is bettrer
	if errtrans := l.svcCtx.SvcHttpModel.TransCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
		_, errInfoTableTransInsert := l.svcCtx.SvcModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceInfo{
			ServiceName: in.ServiceName,
			ServiceDesc: in.ServiceDesc,
		})
		if errInfoTableTransInsert != nil {
			return errInfoTableTransInsert
		}
		res, errTransFindIdByServiceName := l.svcCtx.SvcModel.TransFindIdByServiceName(l.ctx, session, in.ServiceName)
		if errTransFindIdByServiceName != nil {
			return errorx.NewDefaultError("find id by servicename is error")
		}

		_, errHttpTableTransInsert := l.svcCtx.SvcHttpModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceHttpRule{
			ServiceId:      res.Id,
			RuleType:       in.RuleType,
			Rule:           in.Rule,
			NeedHttps:      in.NeedHttps,
			NeedStripUri:   in.NeedStripUri,
			NeedWebsocket:  in.NeedWebsocket,
			UrlRewrite:     in.UrlRewrite,
			HeaderTransfor: in.HeaderTransfor,
		})
		if errHttpTableTransInsert != nil {
			return errHttpTableTransInsert
		}
		_, errAccessControlTableTransInsert := l.svcCtx.SvcAccessControlModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceAccessControl{
			ServiceId:         res.Id,
			OpenAuth:          in.OpenAuth,
			BlackList:         in.BlackList,
			WhiteList:         in.WhiteList,
			ClientipFlowLimit: in.ClientipFlowLimit,
			ServiceFlowLimit:  in.ServiceFlowLimit,
		})
		if errAccessControlTableTransInsert != nil {
			return errAccessControlTableTransInsert
		}

		_, errLoadBalanceTableTransInsert := l.svcCtx.SvcLoadBalanceModel.TransInsert(l.ctx, session, &svcmodel.GatewayServiceLoadBalance{
			ServiceId:              res.Id,
			RoundType:              in.RoundType,
			IpList:                 in.IpList,
			WeightList:             in.WeightList,
			UpstreamConnectTimeout: in.UpstreamConnectTimeout,
			UpstreamHeaderTimeout:  in.UpstreamHeaderTimeout,
			UpstreamIdleTimeout:    in.UpstreamIdleTimeout,
			UpstreamMaxIdle:        in.UpstreamMaxIdle,
		})
		if errLoadBalanceTableTransInsert != nil {
			return errLoadBalanceTableTransInsert
		}

		//
		//_,err_gatewayservicegrpcrule_update := l.svcCtx.SvcModel.Update(l.ctx, &svcmodel.GatewayServiceInfo{
		//	ServiceName: in.ServiceName,
		//	ServiceDesc: in.ServiceDesc,
		//})
		////return err_gatewayservicegrpcrule_update

		return nil
	}); errtrans != nil {
		return nil, errors.New("trans add http table error")
	}
	return &svcclient.ServiceAddHttpResp{}, nil
}
